package com.springmvc.shangguigu.handlers;

import com.springmvc.shangguigu.dao.DepartmentDao;
import com.springmvc.shangguigu.dao.EmployeeDao;
import com.springmvc.shangguigu.entities.Employee;
import com.springmvc.shangguigu.exception.UserNameNotMatchPasswordException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * EmployeeHandler--SpringMVC-test
 * ≈
 *
 * @author: Jovi
 * @createTime: 2018-09-11 10:25
 **/
@Controller
@RequestMapping("/rest")
public class EmployeeHandler {

    @Autowired
    private EmployeeDao employeeDao;

    @Autowired
    private DepartmentDao departmentDao;

    @Autowired
    private ResourceBundleMessageSource messageSource;

    @RequestMapping("/emps")
    public String list(Map<String, Object> map) {
        map.put("employees", employeeDao.getAll());
        return "shangguigu/views/list";
    }

    @RequestMapping(value = {"emp", "/emp/{id}"}, method = RequestMethod.GET)
    public String input(@Nullable @PathVariable("id") Integer id, Map<String, Object> map) {
        map.put("departments", departmentDao.getDepartments());
        if (id == null) {
            map.put("employee", new Employee());
        } else {
            map.put("employee", employeeDao.get(id));
        }
        return "shangguigu/views/input";
    }

    /**
     * 需校验的 Bean 对象和其• 绑定结果对象或错误对象时成对出现的，它们
     * 之间不允许声明其他的入参
     * @param employee
     * @param result 如果转换出错，Springmvc将会将转换结果放到BindingResult中
     * @return
     */
    @RequestMapping(value = "emp", method = RequestMethod.POST)
    public String save(@Valid Employee employee, BindingResult result,Map<String,Object> map) {
        System.out.println("save:" + employee);

        if (result.getErrorCount() > 0) {
            System.out.println("出错了");
            List<FieldError> fieldErrors = result.getFieldErrors();
            for (FieldError fieldError : fieldErrors) {
                System.out.println(fieldError.getField()+":"+fieldError.getDefaultMessage());
            }

            //若验证出错，则转向定制的页面
            return "shangguigu/views/input";
        }

        employeeDao.save(employee);
        return "redirect:/rest/emps";
    }

    @RequestMapping(value = "emp/{id}", method = RequestMethod.DELETE)
    public String delete(@PathVariable("id") Integer id) {
        employeeDao.delete(id);
        return "redirect:/rest/emps";
    }

    //可以将2个方法写在同一个里面利用@Nullable注解。添加和修改用的是同一个页面
    // @RequestMapping(value = "/emp/{id}", method = RequestMethod.GET)
    // public String input(@PathVariable("id") Integer id, Map<String, Object> map) {
    //     //这里的employee必须和表单回显的modelAttribute 一致
    //     map.put("employee", employeeDao.get(id));
    //     map.put("departments", departmentDao.getDepartments());
    //     return "shangguigu/views/input";
    // }

    @RequestMapping(value = "/emp", method = RequestMethod.PUT)
    public String update(Employee employee) {
        employeeDao.save(employee);
        return "redirect:/rest/emps";
    }

    @ModelAttribute
    public void getEmployee(@RequestParam(value = "id", required = false) Integer id,
                            Map<String, Object> map) {
        if (id != null) {
            map.put("employee", employeeDao.get(id));
        }
    }

    @RequestMapping("/testConverter")
    public String testConverter(@RequestParam("employee") Employee employee) {
        employeeDao.save(employee);
        System.out.println("save" + employee);
        return "redirect:/rest/emps";
    }

    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        //不赋值给lastName字段
        webDataBinder.setDisallowedFields("lastName");
    }

    @ResponseBody
    @RequestMapping("/testJson")
    public Collection<Employee> testJson() {
        return employeeDao.getAll();
    }

    @RequestMapping("/testResponseEntity")
    public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {

        byte[] body;

        ServletContext servletContext = session.getServletContext();
        InputStream is = servletContext.getResourceAsStream("/shangguigu/files/abc.txt");
        body = new byte[is.available()];
        is.read(body);

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "attachment;filename=abc.txt");

        HttpStatus statusCode = HttpStatus.OK;

        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(body,headers,statusCode);
        return responseEntity;
    }

    @RequestMapping("/i18n")
    public String testI18n(Locale locale) {
        String message = messageSource.getMessage("i18n.user", null, locale);
        System.out.println(message);
        return "shangguigu/i18n";
    }

    @RequestMapping("/testFileUpload")
    public String testFileUpload(@RequestParam("desc") String desc, @RequestParam("file") MultipartFile file) throws IOException {
        System.out.println("desc" + desc);
        System.out.println("OriginalFilename"+file.getOriginalFilename());
        System.out.println("InputStream"+file.getInputStream());
        return "shangguigu/views/list";
    }

    @RequestMapping("/testExceptionHandlerExceptionResolver")
    public String testExceptionHandlerExceptionResolver(@RequestParam("i") int i) {
        System.out.println("result"+10/i);
        return "shangguigu/views/list";
    }

    /**
     * 1.在@ExceptionHandler方法的入参中，可以加入Exception类型的参数，该参数既对应发生的异常对象
     * 2.@ExceptionHandler方法的入参中不能传入Map,若希望把异常传到页面上，需要使用ModelAndView作为返回值
     * 3.@ExceptionHandler方法标记的异常有优先级的问题
     * 4.@ControllerAdvice 如果在当前Handler 中找不到@ExceptionHandler方法来处理当前方法出现的异常，
     * 则将去@ControllerAdvice中查查找@ExceptionHandler
     * @param e
     * @return
     */
    @ExceptionHandler({ArithmeticException.class})
    public ModelAndView handlerArithmeticException(Exception e) {
        System.out.println("出异常了：" + e);
        ModelAndView mv = new ModelAndView("shangguigu/views/error");
        mv.addObject("exception", e);
        return mv;
    }

    /**
     * 测试UserNameNotMatchPasswordException的时候需要注释掉该方法
     * @param e
     * @return
     */
    // @ExceptionHandler({RuntimeException.class})
    // public ModelAndView handlerRuntimeException(Exception e) {
    //     System.out.println("[出异常了]：" + e);
    //     ModelAndView mv = new ModelAndView("shangguigu/views/error");
    //     mv.addObject("exception", e);
    //     return mv;
    // }

    /**
     * !@ResponseStatus 修饰方法的时候会直接跳到错误页面，报错误信息，
     * @param i
     * @return
     */
    @ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "测试用户名和密码不匹配")
    @RequestMapping("/testResponseStatusExceptionResolver")
    public String testResponseStatusExceptionResolver(@RequestParam("i")int i){
        if (i == 13) {
            throw new UserNameNotMatchPasswordException();
        }
        System.out.println("testResponseStatusExceptionResolver");
        return "shangguigu/views/list";
    }

    @RequestMapping(value = "/testDefaultHandlerExceptionResolver",method = RequestMethod.POST)
    public String testDefaultHandlerExceptionResolver() {
        System.out.println("testDefaultHandlerExceptionResolver....");
        return "shangguigu/views/list";
    }

    @RequestMapping(value = "/testSimpleMappingExceptionResolver")
    public String testSimpleMappingExceptionResolver(@RequestParam("i") int i) {
        String[] vals = new String[10];
        System.out.println(vals[i]);
        return "shangguigu/views/list";
    }


}
